module executor.group.GroupExecutor;

import msgtrans;
import message.Constants;
import message.MsgDefine;
import google.protobuf;
import hunt.logging;
import std.array;
import std.conv : to;
import hunt.util.Serialize;
import client.GateServerClient;
import client.MsgServerClient;
import service.GroupService;
import service.ApplyService;
import service.SearchUserService;
import bootstrap.DatabaseBootstrap;
import core.stdc.time;
import hunt.framework;

/**
群功能模块
**/

@TransportServer(LogicServerName)
class GroupExecutor : AbstractExecutor!(GroupExecutor){

    //创建群接口
    @MessageId(MESSAGE.CMD_GREATE_GROUP_REQ)
    void createGroup(TransportContext ctx, MessageBuffer buffer)
    {
        auto req = new CreateGroupREQ();
        buffer.data.fromProtobuf!CreateGroupREQ(req);
        TransportSession msgClient = null;

        if (req.users.length > 1)
        {
             User[] users = ApplyService.getUsers(req.users, req.users[0]);
             int id = GroupService.addGroup(req, users);
             logInfo("createGroup ----- id : %d" , id);
             JoinGroup joinGroup = new JoinGroup;
             joinGroup.groupId = to!string(id);
             joinGroup.aliasName = req.groupName;
             joinGroup.member = users;
             joinGroup.validation = 0;

            ChatMapAction chatMapAction = new ChatMapAction;
            chatMapAction.chatId = to!string(id);
            chatMapAction.type = ChatMapActionType.CREATE;
            chatMapAction.manager = users[0].id;
            chatMapAction.timestamp = core.stdc.time.time(null);
            foreach(User u ; users)
            {
                chatMapAction.member ~= u.id;
            }
            
            msgClient = MsgServerClient.getInstance().getForwardClient(id);
            msgClient.send(new MessageBuffer(MESSAGE.CMD_CHAT_MAP_ACTION, chatMapAction.toProtobuf.array)); //向msgserver同步chatId对应关系列表

            foreach (User u ; joinGroup.member)
            {
                joinGroup.destination = u.id;
                msgClient = MsgServerClient.getInstance().getForwardClient(to!int(u.id));
                msgClient.send(new MessageBuffer(MESSAGE.CMD_JOIN_GROUP,joinGroup.toProtobuf.array));//向群全部成员发送创建群回调
            }

            // InviteGroup inviteGroup = new InviteGroup;
            // inviteGroup.groupId = to!string(id);
            // inviteGroup.aliasName = req.aliasName;
            // inviteGroup.userId = req.userId;
            //    foreach(User u ; unAdopt)
            //    {
            //         inviteGroup.destination = u.id;
            //         msgClient = MsgServerClient.getInstance().getForwardClient(to!int(u.id));
            //         msgClient.send(new MessageBuffer(MESSAGE.CMD_INVITE_GROUP,inviteGroup.toProtobuf.array));
            //    }
        }
    }

    // 邀请离线人员入群接口
    @MessageId(MESSAGE.CMD_OFFLINE_INVITE_GROUP)
    void putOfflineInviteGroup(TransportContext ctx, MessageBuffer buffer) {
        ApplyGroup applyGroup = new ApplyGroup;
        buffer.data.fromProtobuf!ApplyGroup(applyGroup);
        GroupService.addGroupApply(applyGroup, 0);
    }

    //处理群邀请接口
    @MessageId(MESSAGE.CMD_DEAL_GROUP_REQ)
    void dealGroupApply(TransportContext ctx, MessageBuffer buffer) {
        DealApplyGroup dealApplyGroup = new DealApplyGroup;
        buffer.data.fromProtobuf!DealApplyGroup(dealApplyGroup);

        if(GroupService.isExist(dealApplyGroup.userId, dealApplyGroup.groupId))
        {
            logInfo("ignorn dealGroupApply %s group %s", dealApplyGroup.userId, dealApplyGroup.groupId);
            return;
        }

        TransportSession msgClient = null;
        GroupService.updateGroupApplyStatus(dealApplyGroup.groupId, dealApplyGroup.fromId, dealApplyGroup.userId, dealApplyGroup.succeeded);
        if (dealApplyGroup.succeeded)
        {
            ChatMapAction chatMapAction = new ChatMapAction;
            chatMapAction.chatId = dealApplyGroup.groupId;
            chatMapAction.type = ChatMapActionType.ADD;
            chatMapAction.member = [dealApplyGroup.userId];
            chatMapAction.manager = dealApplyGroup.fromId;
            chatMapAction.timestamp = core.stdc.time.time(null);
            msgClient =    MsgServerClient.getInstance().getForwardClient(to!int(dealApplyGroup.groupId));
            msgClient.send(new MessageBuffer(MESSAGE.CMD_CHAT_MAP_ACTION, chatMapAction.toProtobuf.array));

            auto em = defaultEntityManager();
            em.getTransaction().begin();
            User user = SearchUserService.selectUser(dealApplyGroup.userId,dealApplyGroup.fromId);
            GroupService.addGroupUser(dealApplyGroup.userId, to!int(dealApplyGroup.groupId), user.nickname, em);
            em.getTransaction().commit();
            em.close();

            JoinGroup joinGroup = GroupService.selectGroupInfo(dealApplyGroup.groupId,dealApplyGroup.userId);

            msgClient = MsgServerClient.getInstance().getForwardClient(to!int(dealApplyGroup.userId));
            msgClient.send(new MessageBuffer(MESSAGE.CMD_JOIN_GROUP, joinGroup.toProtobuf.array));
        }
    }

    // 退群接口
    @MessageId(MESSAGE.CMD_LEAVE_GROUP)
    void leaveGroup(TransportContext ctx, MessageBuffer buffer)
    {
        LeaveGroup leaveGroup = new LeaveGroup;
        buffer.data.fromProtobuf!LeaveGroup(leaveGroup);

        GroupService.deleteGroupUser(leaveGroup.fromId, leaveGroup.groupId);
        TransportSession msgClient = null;
        ChatMapAction chatMapAction = new ChatMapAction;
        chatMapAction.chatId = leaveGroup.groupId;
        chatMapAction.type = ChatMapActionType.DELETE;
        chatMapAction.member = [leaveGroup.fromId];
        msgClient = MsgServerClient.getInstance().getForwardClient(to!int(leaveGroup.groupId));
        msgClient.send(new MessageBuffer(MESSAGE.CMD_CHAT_MAP_ACTION, chatMapAction.toProtobuf.array));
    }

    //解散群接口
    @MessageId(MESSAGE.CMD_CANCEL_GROUP)
    void cancelGroup(TransportContext ctx, MessageBuffer buffer) {
        CancelGroup cancelGroup = new CancelGroup;
        buffer.data.fromProtobuf!CancelGroup(cancelGroup);
        TransportSession msgClient = null;
        ChatMapAction chatMapAction = new ChatMapAction;
        chatMapAction.chatId = cancelGroup.groupId;
        chatMapAction.type = ChatMapActionType.DESTROY;
        chatMapAction.member = [];
        msgClient =    MsgServerClient.getInstance().getForwardClient(to!int(cancelGroup.groupId));
        msgClient.send(new MessageBuffer(MESSAGE.CMD_CHAT_MAP_ACTION, chatMapAction.toProtobuf.array));

        GroupService.cancelGroup(cancelGroup.fromId, cancelGroup.groupId);
    }

    //踢出群接口
    @MessageId(MESSAGE.CMD_KICK_USER)
    void kickUser(TransportContext ctx, MessageBuffer buffer) {
        KickUser kickUser = new KickUser;
        buffer.data.fromProtobuf!KickUser(kickUser);

        if (!GroupService.isCreator(kickUser.fromId, kickUser.groupId))
        {
            return;
        }

        GroupService.deleteGroupUser(kickUser.userId, kickUser.groupId);

        TransportSession msgClient = null;
        ChatMapAction chatMapAction = new ChatMapAction;
        chatMapAction.chatId = kickUser.groupId;
        chatMapAction.type = ChatMapActionType.KICK;
        User user = new User;
        user.id = kickUser.userId;
        chatMapAction.member = [user.id];
        msgClient =    MsgServerClient.getInstance().getForwardClient(to!int(kickUser.groupId));
        msgClient.send(new MessageBuffer(MESSAGE.CMD_CHAT_MAP_ACTION, chatMapAction.toProtobuf.array));
    }

    @MessageId(MESSAGE.CMD_APPLY_GROUP)
    void applyGroup(TransportContext ctx, MessageBuffer buffer) {
        //ApplyGroup applyGroup = new ApplyGroup;
        //buffer.data.fromProtobuf!ApplyGroup(applyGroup);
        //
        //User user = SearchUserService.selectUser(applyGroup.fromId);
        //if (user is null)
        //{
        //    return;
        //}
        //TransportSession msgClient = null;
        //ChatMapAction chatMapAction = new ChatMapAction;
        //chatMapAction.chatId = applyGroup.groupId;
        //chatMapAction.type = ChatMapActionType.ADD;
        //chatMapAction.member = [user];
        //msgClient =    MsgServerClient.getInstance().getForwardClient(to!int(applyGroup.groupId));
        //msgClient.send(new MessageBuffer(MESSAGE.CMD_CHAT_MAP_ACTION, chatMapAction.toProtobuf.array));
        //
        //GroupService.addGroupUser(applyGroup.fromId, to!int(applyGroup.groupId), applyGroup.username);
        //JoinGroup joinGroup = GroupService.selectGroupInfo(applyGroup.groupId,applyGroup.fromId);
        //
        //msgClient =    MsgServerClient.getInstance().getForwardClient(to!int(applyGroup.fromId));
        //msgClient.send(new MessageBuffer(MESSAGE.CMD_JOIN_GROUP, joinGroup.toProtobuf.array));
    }

    //更新群信息接口
    @MessageId(MESSAGE.CMD_UPDATE_GROUP_INFO)
    void updateGroupInfo(TransportContext ctx, MessageBuffer buffer) {
        auto req = new UpdateGroupInfo;
        buffer.data.fromProtobuf!UpdateGroupInfo(req);
        GroupService.updateGroupInfo(req);
    }

    //邀请入群接口
    @MessageId(MESSAGE.CMD_INVITE_GROUP)
    void groupInvite(TransportContext ctx, MessageBuffer buffer) {
            auto req = new InviteGroup;
            buffer.data.fromProtobuf!InviteGroup(req);
            TransportSession msgClient = null;
            string manager;
            foreach (string destination ; req.destination)
            {
                if (GroupService.isExist(destination, req.groupId))
                {
                    return;
                }

                if(GroupService.needValidation(req.groupId,req.userId,manager))
                {

                    ApplyGroup applyGroup = new ApplyGroup;
                    applyGroup.fromId = req.userId;
                    applyGroup.groupId = req.groupId;
                    applyGroup.username = req.aliasName;
                    applyGroup.newMember = destination;
                    applyGroup.destination = manager;

                    msgClient =    MsgServerClient.getInstance().getForwardClient(to!int(manager));
                    msgClient.send(new MessageBuffer(MESSAGE.CMD_APPLY_GROUP, applyGroup.toProtobuf.array));
                    logInfo("groupInvite needValidation to %s",manager);
                }
                else
                {
                    GroupService.groupInvite(req,destination);

                    ChatMapAction chatMapAction = new ChatMapAction;
                    chatMapAction.chatId = req.groupId;
                    chatMapAction.type = ChatMapActionType.ADD;
                    chatMapAction.member = [destination];
                    chatMapAction.manager = req.userId;
                    chatMapAction.timestamp = core.stdc.time.time(null);
                    msgClient =    MsgServerClient.getInstance().getForwardClient(to!int(req.groupId));
                    msgClient.send(new MessageBuffer(MESSAGE.CMD_CHAT_MAP_ACTION, chatMapAction.toProtobuf.array));

                    JoinGroup joinGroup = GroupService.selectGroupInfo(req.groupId,destination);

                    msgClient =    MsgServerClient.getInstance().getForwardClient(to!int(destination));
                    msgClient.send(new MessageBuffer(MESSAGE.CMD_JOIN_GROUP, joinGroup.toProtobuf.array));
                }
            }

    }

    //设置群名称接口
    @MessageId(MESSAGE.CMD_SET_GROUP_NAME_REQ)
    void setGroupName(TransportContext ctx, MessageBuffer buffer) {
        auto req = new SetGroupNameREQ;
        buffer.data.fromProtobuf!SetGroupNameREQ(req);
        GroupService.setGroupName(req.groupId, req.groupName);

        auto msgClient =    MsgServerClient.getInstance().getForwardClient(to!int(req.groupId));
        msgClient.send(new MessageBuffer(MESSAGE.CMD_SET_GROUP_NAME_REQ, req.toProtobuf.array));
    }
}

